﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SilverChart.Core.Service;
using System.Collections.Generic;

namespace SilverChart.Core.Configuration {
    public abstract class AbstractConfigurationParser : ConfigurationParser {
        public Boolean TryGetValue<T>(String itemName, out T value) {
            Type configurationItemType = GetMatchedCongifurationItem<T>(itemName);
            if (configurationItemType != null) {
                value = (T)CreateConfigurationItem(configurationItemType, itemName);
                if (value == null && typeof(T) != typeof(ConfigurationItem)
                    //TODO Is this necessary?
                    /*&& typeof(T) == configurationItemType*/
                    ) {
                    ConfigurationItemAttribute attribute = (ConfigurationItemAttribute)Attribute.
                        GetCustomAttribute(configurationItemType, typeof(ConfigurationItemAttribute));
                    if (attribute.CreateForDefault) {
                        value = (T)AbstractConfigurationItem.CreateInstance(configurationItemType, null);
                    }
                }
                return value != null;
            }

            if (TryGetConvertableTypeValue<T>(GetItemValue(itemName), out value)) {
                return true;
            }

            if (typeof(T) == typeof(ConfigurationItem)) {
                value = (T)CreateConfigurationItem(typeof(DefaultConfigurationItem), itemName);
                return value != null;
            }

            return false;
        }

        protected Type GetMatchedCongifurationItem<T>(String itemName) {
            ConfigurationService service = ServiceManager.Instance.GetService<ConfigurationService>();
            IList<Type> items = service.RegisteredItems(Configuration, itemName);
            if (items != null && items.Count > 0) {
                foreach (Type type in items) {
                    if (typeof(T) == type || typeof(T).IsAssignableFrom(type)) {
                        return type;
                    }
                }
            }
            return null;
        }

        public Boolean TryGetValues<T>(String itemName, out IList<T> values) {
            if (!IsItemSupportCollection(itemName)) {
                values = null;
                return false;
            }

            values = new List<T>();
            Type configurationItemType = GetMatchedCongifurationItem<T>(itemName);
            if (configurationItemType != null) {
                IList<ConfigurationItem> items = CreateConfigurationCollectionItem(configurationItemType, itemName);
                foreach (ConfigurationItem item in items) {
                    values.Add((T)item);
                }
                return true;
            }

            IList<String> itemValues = GetItemValues(itemName);
            foreach (String itemValue in itemValues) {
                T value;
                if (TryGetConvertableTypeValue<T>(itemValue, out value)) {
                    values.Add(value);
                }
            }
            if (values.Count > 0) {
                return true;
            }

            if (typeof(T) == typeof(ConfigurationItem)) {
                IList<ConfigurationItem> items = CreateConfigurationCollectionItem(typeof(DefaultConfigurationItem), itemName);
                foreach (ConfigurationItem item in items) {
                    values.Add((T)item);
                }
                return true;
            }

            values = null;
            return false;
        }

        protected Boolean TryGetConvertableTypeValue<T>(String itemValue, out T value) {
            value = default(T);
            if (itemValue == null) {
                return false;
            }

            IList<ConfigurationConverter<T>> converts = ServiceManager.Instance.GetServices<ConfigurationConverter<T>>();
            Boolean result = false;
            foreach (ConfigurationConverter<T> convert in converts) {
                try {
                    result = convert.Convert(itemValue, out value);
                    if (result) break;
                }
                catch {
                }
            }
            return result;
        }
        public ConfigurationItem Configuration { get; set; }

        public abstract String GetItemValue(String itemName);

        protected abstract ConfigurationItem CreateConfigurationItem(Type type, String itemName);
        protected abstract IList<ConfigurationItem> CreateConfigurationCollectionItem(Type type, String itemName);
        protected abstract IList<String> GetItemValues(String itemName);
        protected abstract Boolean IsItemSupportCollection(String itemName);
    }
}
